#pragma once

#include <AVUITriggerBase.h>
#include <AVUISetterBaseCollection.h>

namespace AVUI {

/// <summary>Represents a trigger that applies property values or performs actions conditionally.</summary>
class Trigger : public TriggerBase
{
public:
    DECLARE_ELEMENT(Trigger, TriggerBase);

#pragma region Public Methods

    /// <summary>Initializes a new instance of the <see cref="T:System.Windows.Trigger" /> class.</summary>
    Trigger() : m_pProperty(NULL), m_pValue(DependencyProperty::get_UnsetValue()) { }

#pragma endregion Public Methods

#pragma region Public Properties

    /// <summary>Gets or sets the property that returns the value that is compared with the <see cref="P:System.Windows.Trigger.Value" /> property of the trigger. The comparison is a reference equality check.</summary>
    /// <returns>A <see cref="T:System.Windows.DependencyProperty" /> that returns the property value of the element. The default value is null.</returns>
    /// <exception cref="T:System.ArgumentException">A <see cref="T:System.Windows.Style" /> cannot contain a <see cref="T:System.Windows.Trigger" /> that refers to the <see cref="T:System.Windows.Style" /> property.</exception>
    /// <exception cref="T:System.InvalidOperationException">After a <see cref="T:System.Windows.Trigger" /> is in use, it cannot be modified.</exception>
    DependencyProperty* get_Property() { VerifyAccess(); return m_pProperty; }
    void set_Property(DependencyProperty* pValue);
    DECLARE_PROPERTY(Property, DependencyProperty, false);
 
    /// <summary>Gets a collection of <see cref="T:System.Windows.Setter" /> objects, which describe the property values to apply when the specified condition has been met.</summary>
    /// <returns>The default value is null.</returns>
    SetterBaseCollection* get_Setters();
    DECLARE_READONLY_PROPERTY(Setters, SetterBaseCollection, true);

    /// <summary>Gets or sets the name of the object with the property that causes the associated setters to be applied.</summary>
    /// <returns>The default property is null. If this property is null, then the <see cref="P:System.Windows.Trigger.Property" /> property is evaluated with respect to the element this style or template is being applied to (the styled parent or the templated parent).</returns>
    /// <exception cref="T:System.InvalidOperationException">After a <see cref="T:System.Windows.Trigger" /> is in use, it cannot be modified.</exception>
    String* get_SourceName() { VerifyAccess(); return m_pSourceName; }
    void set_SourceName(String* pValue);
    DECLARE_PROPERTY(SourceName, String, false);

    /// <summary>Gets or sets the value to be compared with the property value of the element. The comparison is a reference equality check.</summary>
    /// <returns>The default value is null. See also the Exceptions section.</returns>
    /// <exception cref="T:System.ArgumentException">Only load-time <see cref="T:System.Windows.Markup.MarkupExtension" />s are supported.</exception>
    /// <exception cref="T:System.ArgumentException">Expressions such as bindings are not supported.</exception>
    /// <exception cref="T:System.InvalidOperationException">After a <see cref="T:System.Windows.Trigger" /> is in use, it cannot be modified.</exception>
    Object* get_Value() { VerifyAccess(); return m_pValue; }
    void set_Value(Object* pValue);
    DECLARE_PROPERTY_BEGIN(Value, Object, false)
        DECLARE_ATTRIBUTE_DEPENDSON(SourceName)
        DECLARE_ATTRIBUTE_DEPENDSON(Property)
    DECLARE_PROPERTY_END()

#pragma endregion Public Properties

public:

#pragma region Internal Methods

    static Setter* CheckChildIsSetter(Object* pO);
    virtual bool GetCurrentState(DependencyObject* pContainer, UncommonField<HybridDictionaryArray>* pDataField) AVUI_OVERRIDE;
    virtual void Seal() AVUI_OVERRIDE;

#pragma endregion Internal Methods

private:

#pragma region Private Fields

    DependencyProperty* m_pProperty;
    TRefCountedPtr<SetterBaseCollection> m_pSetters;
    TRefCountedPtr<String> m_pSourceName;
    TRefCountedPtr<Object> m_pValue;

#pragma endregion Private Fields

};

}; // namespace AVUI
